﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MBT.Modeling
{
 
	/// <summary>
	/// Model slicer.
	/// </summary>
    public class ModelSlicer //: IFormalismElement
    {

        #region New Methods to support DLLs
        public Dictionary<string, string> domainFunctions = new Dictionary<string, string>();
		
        /// <summary>
        /// When using DLLs, I use this instead of "paramBinderFunction"?
        /// </summary>
        class DomainInfo
        {
            /*
             * //When we use a method to generate parameters
            MethodInfo method;
            //When we use a field to generate parameters
            FieldInfo field;
			 */
			
            public bool useMethod;
            //ID of domain
            public string DomainID;
			
			/// <summary>
			/// Initializes a new instance of the <see cref="MBT.Modeling.ModelSlicer.DomainInfo"/> class.
			/// </summary>
			/// <param name='method'>
			/// Method info.
			/// </param>
            public DomainInfo(MethodInfo method)
            {
                useMethod = true;
                //this.method = method;
                System.Attribute[] attrs = System.Attribute.GetCustomAttributes(method);

                foreach (System.Attribute at in attrs)
                {
                    if (at is DomainDef)
                    {

                        DomainID = (at as DomainDef).DomainID;


                        break;
                    }
                }
            }
			
			/// <summary>
			/// Initializes a new instance of the <see cref="MBT.Modeling.ModelSlicer.DomainInfo"/> class.
			/// </summary>
			/// <param name='field'>
			/// Field ino.
			/// </param>
            public DomainInfo(FieldInfo field)
            {
                useMethod = false;
                //this.field = field;
            }

            ///// <summary>
            ///// Generate list of possible values for this domain
            ///// </summary>
            ///// <returns></returns>
            //public IList Generate()
            //{
            //    return null;
            //}
        }
		
        List<DomainInfo> dinfos = new List<DomainInfo>();
        public void RegisterDomain(MethodInfo method)
        {
            DomainInfo dom = new DomainInfo(method);
            domainFunctions.Add(dom.DomainID, method.Name);
            dinfos.Add(dom);
        }

        public void RegisterSkipState(MethodInfo method)
        {
            //SkipStateFunction = new ExecFunction(method);
        }
        #endregion


        //Function SkipStateFunction;
        //public List<Function> skipTransitionFunctions = new List<Function>();

        string tag;
        public string Tag { get { return tag; } }
        public ModelSlicer()
        {
            tag = "Slicer";
        }

        //[Browsable(false)]
        //public Function SkipState
        //{
        //    get
        //    {
        //        return SkipStateFunction;
        //    }
        //    set
        //    {
        //        SkipStateFunction = value;
        //    }
        //}

        //protected List<Event> events = new List<Event>();
        //public Event this[string eventID]
        //{
        //    get
        //    {
        //        foreach (Event v in events)
        //            if (v.ID == eventID)
        //            {
        //                return v;
        //            }
        //        return null;
        //    }
        //}

        //public List<Event> Events
        //{
        //    get
        //    {
        //        return events;
        //    }
        //}

        #region Gui Helper
        //        [EditorAttribute(typeof(CodePropertyEditor), typeof(UITypeEditor)), DisplayName("SkipState Function")]
        //public string SkipStateCode
        //{
        //    get
        //    {
        //        return SkipStateFunction.Code;
        //    }
        //    set
        //    {
        //        SkipStateFunction.Code = value;
        //    }
        //}
        #endregion

        //public void WriteXml(XmlDatabaseHelper db)
        //{
        //    XmlDatabaseHelper.XmlRow row = db.AddXmlRow("Events");
        //    foreach (Event e in Events)
        //    {
        //        XmlDatabaseHelper.XmlRow erow = row.AddXmlRow("Event");
        //        erow.Attributes["ID"] = e.ID;
        //        XmlDatabaseHelper.XmlRow pre = erow.AddXmlRow("Precondition");
        //        pre.Value = e.PreCondition.Code;
        //        pre.Attributes["type"] = "bool";

        //        pre = erow.AddXmlRow("Weight");
        //        pre.Value = e.Weight.Code;
        //        pre.Attributes["type"] = "float";

        //        pre = erow.AddXmlRow("Priority");
        //        pre.Value = e.Rank.Code;
        //        pre.Attributes["type"] = "int";

        //        pre = erow.AddXmlRow("Delay");
        //        pre.Value = e.Delay.Code;
        //        pre.Attributes["type"] = "float";

        //        pre = erow.AddXmlRow("ActionAttrib");
        //        pre.Value = e.ActionAttrib.Code;
        //        pre.Attributes["type"] = "void";

        //        pre = erow.AddXmlRow("Reactivation");
        //        pre.Value = e.ReActivation.Code;
        //        pre.Attributes["type"] = "bool";

        //    }

        //}

        //public List<ParamsBinder> paramBinders = new List<ParamsBinder>();
        //public List<ParamsBinder> paramBindersOfModel = new List<ParamsBinder>();

        public enum BindingType { bindedByFunction, bindedByDomin, notBinded };
        //public BindingType whatIsBindingType(string eventID, string paramID)
        //{
        //    for (int i = 0; i < paramBindersOfModel.Count; i++)
        //    {
        //        //Find Event
        //        if (paramBindersOfModel[i].inAction.Equals(eventID))
        //        {
        //            for (int j = 0; j < paramBindersOfModel[i].bindingDomainList.Count; j++)
        //            {
        //                if (paramBindersOfModel[i].bindingDomainList[j].paramID.Equals(paramID))
        //                    return BindingType.bindedByDomin;
        //            }
        //            for (int j = 0; j < paramBindersOfModel[i].bindingFunctionList.Count; j++)
        //            {
        //                if (paramBindersOfModel[i].bindingFunctionList[j].paramID.Equals(paramID))
        //                    return BindingType.bindedByFunction;
        //            }
        //        }
        //    }
        //    return BindingType.notBinded;
        //}


        //public string whatIsDomianID(string eventID, string paramID)
        //{
        //    for (int i = 0; i < paramBindersOfModel.Count; i++)
        //    {
        //        //Find Event
        //        if (paramBindersOfModel[i].inAction.Equals(eventID))
        //        {
        //            for (int j = 0; j < paramBindersOfModel[i].bindingDomainList.Count; j++)
        //            {
        //                if (paramBindersOfModel[i].bindingDomainList[j].paramID.Equals(paramID))
        //                    return paramBindersOfModel[i].bindingDomainList[j].DomainID;
        //            }
        //        }
        //    }
        //    return "DomianNotFount";
        //}

        //public static ModelSlicer ReadXML(EnGine.Base.XmlDatabaseHelper db)
        //{
        //    //Skip state function
        //    ModelSlicer slicer = new ModelSlicer();
        //    slicer.SkipState = new Function("SkipState", db["ModelSlicer"][0]["SkipState"], "bool");

        //    //param generators functions
        //    XmlDatabaseHelper.XmlRow row = db["ModelSlicer"][0]["ParamBinding"];
        //    foreach (XmlDatabaseHelper.XmlRow binderRow in row.RowsOf("inAction"))
        //    {
        //        ParamsBinder binder = new ParamsBinder();
        //        binder.inAction = binderRow.GetAttribute("actionID");

        //        foreach (XmlDatabaseHelper.XmlRow r1 in binderRow.RowsOf("Binder"))
        //        {
        //            paramBinderFunction pb = new paramBinderFunction();
        //            pb.paramID = r1.GetAttribute("paramID");
        //            pb.parmType = r1.GetAttribute("paramType");
        //            pb.BindingFunction = new Function(binder.inAction + "_" + pb.paramID + "_ParamGenerator", r1.Value, "List<" + pb.parmType + ">");
        //            binder.bindingFunctionList.Add(pb);
        //        }

        //        foreach (XmlDatabaseHelper.XmlRow r1 in binderRow.RowsOf("BindToDomain"))
        //        {
        //            DomainBinder dbinder = new DomainBinder();
        //            dbinder.paramID = r1.GetAttribute("paramID");
        //            dbinder.DomainID = r1.GetAttribute("DomainID");
        //            binder.bindingDomainList.Add(dbinder);
        //        }
        //        slicer.paramBindersOfModel.Add(binder);
        //    }


        //    //skip transitions function
        //    row = db["ModelSlicer"][0]["SkipTransitions"];
        //    foreach (XmlDatabaseHelper.XmlRow binderRow in row.RowsOf("inTransition"))
        //    {
        //        Function preCondition2 = new Function(binderRow.GetAttribute("transitionID") /*+ "_preformPre2"*/, binderRow.Value, "bool");
        //        slicer.skipTransitionFunctions.Add(preCondition2);
        //    }

        //    return slicer;
        //}

        //#region IFormalismElement Members

        //public string ID
        //{
        //    get { throw new NotImplementedException(); }
        //}

        //#endregion

        //#region ICloneable Members

        //public object Clone()
        //{
        //    throw new NotImplementedException();
        //}

        //#endregion
    }
}
